module sandbox {

    export class DependencyProperty {
        private _name: string;
        private _propertyType: any;
        private _ownerType: any;
        private _propertyMetadata: PropertyMetadata;
        private static  DependencyProperties: { [name: string]: DependencyProperty }


        constructor(name: string, propertyType: any, ownerType: any, propertyMetadata: PropertyMetadata) {
            this._name = name;
            this._propertyType = propertyType;
            this._ownerType = ownerType;
            this._propertyMetadata = propertyMetadata;
        }

        public get Name(): string {
            return this._name;
        }

        public get PropertyType(): any {
            return this._propertyType;
        }

        public get OwnerType(): any {
            return this._ownerType;
        }

        public get DefaultMetadata(): PropertyMetadata {
            return this._propertyMetadata;
        }

        public static Register(name: string, propertyType: any, ownerType: any, typeMetadata: PropertyMetadata, validateValueCallback: (object: any)=> boolean): DependencyProperty {
            var dependencyProperty = new DependencyProperty(name, propertyType, ownerType, typeMetadata);

            DependencyProperty.DependencyProperties[name] = dependencyProperty;

            return dependencyProperty;
        }

    }

    export class PropertyMetadata {

        private _propertyChangedCallback: (d: any, e: DependencyPropertyChangedEventArgs) => void;
        private  _coerceValueCallback : (d:any, baseValue: any)=>any;

        constructor(defaultValue: any, propertyChangedCallback: (d: /*DependencyObject*/ any, e: DependencyPropertyChangedEventArgs)=> void,
            coerceValueCallback: (d: /*DependencyObject*/any, baseValue: any)=> any) {
            this._propertyChangedCallback = propertyChangedCallback;
            this._coerceValueCallback = coerceValueCallback;
        }

        public get GetPropertyChangedCallback(): (d: any, e: DependencyPropertyChangedEventArgs)=> void {
            return this._propertyChangedCallback;
        }

        public get GetCoerceValueCallback(): (d: any, baseValue: any)=> any {
            return this._coerceValueCallback;
        }
    }

    export class DependencyPropertyChangedEventArgs {
        private _property: DependencyProperty;
        private  _oldValue :any;
        private _newValue: any;
        constructor(property: DependencyProperty, oldValue: any, newValue: any) {
            this._property = property;
            this._oldValue = oldValue;
            this._newValue = newValue;
        }

        public get property(): any {
            return this._property;
        }

        public get newValue(): any {
            return this._newValue;
        }

        public get oldValue(): any {
            return this._oldValue;
        }

    }
}

interface HTMLInputElement {
    TextProperty: sandbox.DependencyProperty;
}

function TextPropertyChangedCallback(d: any, e: sandbox.DependencyPropertyChangedEventArgs) {
    var inputElement = <HTMLInputElement>d;
    inputElement.value = e.newValue;
}

function TextCoerceValueCallback(d: any, baseValue: any) {
    var inputElement = <HTMLInputElement>d;

}

var TextPropertyMetadata = new sandbox.PropertyMetadata("", TextPropertyChangedCallback, TextCoerceValueCallback);

HTMLInputElement.prototype.TextProperty = sandbox.DependencyProperty.Register("Text", String.prototype, HTMLInputElement.prototype, TextPropertyMetadata, null);

